package zb.blog.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.util.Auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import zb.blog.base.bean.Result;
import zb.blog.base.cache.DataToCache;
import zb.blog.base.global.GlobalVar;
import zb.blog.base.sessionScope.SessionScope;
import zb.blog.base.util.EncryptUtil;
import zb.blog.base.util.StringUtil;
import zb.blog.bean.ArticleBean;
import zb.blog.dao.ArticleDao;
import zb.blog.dao.CommentDao;
import zb.blog.dao.PraiseDao;
import zb.blog.service.IArticleService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ArticleService implements IArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Autowired
    private PraiseDao praiseDao;
    @Autowired
    private CommentDao commentDao;

    @Override
    public PageInfo<ArticleBean> getArticleByStatus(int pageNum, int pageSize, Map<String, Object> param) {
        PageHelper.startPage(pageNum, pageSize);
        List<ArticleBean> list = articleDao.getArticleByStatus(param);
        PageInfo<ArticleBean> pageInfo = new PageInfo<>(list);
        List<ArticleBean> collect = pageInfo.getList().stream().map(x -> {
            x.setFront_img(GlobalVar.QNY_ARTICLE_URL + "/" + x.getFront_img());
            return x;
        }).collect(Collectors.toList());
        pageInfo.setList(collect);
        return pageInfo;
    }

    @Override
    public Result addArticle(ArticleBean articleBean, HttpSession session) {
        Result r = new Result();
        try {
            int userId = SessionScope.getLoginAuth().getUser().getId();
            articleBean.setUser_id(userId);
            articleDao.addArticle(articleBean);
            praiseDao.addPraise(EncryptUtil.customDecrypt(articleBean.getId()), new Integer[]{1, 2, 3, 4, 5});//这里有5中类型的赞,对应到blog_praise.id
            r.setSuccess(GlobalVar.SUCCESS);
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            r.setSuccess(GlobalVar.FAIL);
            //throw new RuntimeException();//这种抛出异常之后无返回值

            //当异常被catch后，spring捕捉不到异常，因而不能回滚事务
            /**
             * 手动回滚的好处是:
             * 1.可以在catch中自定义异常处理并且能实现事务的回滚
             * 2.可以在catch中有返回值
             */
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return r;
        }
    }

    @Override
    public Result getArticleById(String id) {
        Result r = new Result();
        if (id == null || id.length() <= 0) {
            r.setMsg("参数错误，查询文章失败！");
            r.setSuccess(GlobalVar.FAIL);
            return r;
        }
        try {
            int articleId = EncryptUtil.customDecrypt(id);
            ArticleBean articleBean = articleDao.getArticleById(articleId);
            articleBean.setArticle_url(GlobalVar.QNY_ARTICLE_URL);
            if (articleBean == null) {
                r.setSuccess(GlobalVar.FAIL);
                r.setMsg("找不到对应的文章！");
                return r;
            }
            //查询上一篇文章和下一篇文章
            List<Map<String, Object>> list = articleDao.getArticleByIdNear(EncryptUtil.customDecrypt(articleBean.getId()));
            if (list == null) {
                articleBean.setPrevId(-1);
                articleBean.setNextId(-1);
                articleBean.setPrevArticleTitle("<<查询失败>>");
                articleBean.setNextArticleTitle("<<查询失败>>");
            } else {
                List<Map<String, Object>> next = list.stream().filter((x) -> (long) x.get("difftime") < 0).limit(1).collect(Collectors.toList());
                List<Map<String, Object>> prev = list.stream().filter((x) -> (long) x.get("difftime") > 0).limit(1).collect(Collectors.toList());
                if (prev.size() == 1) {
                    Integer prevId = (Integer) prev.get(0).get("id");
                    String prevTitle = (String) prev.get(0).get("title");
                    articleBean.setPrevId(prevId);
                    articleBean.setPrevArticleTitle(prevTitle);
                } else {
                    articleBean.setPrevId(-1);
                    articleBean.setPrevArticleTitle("已经是第一篇文章了！");
                }
                if (next.size() == 1) {
                    Integer nextId = (Integer) next.get(0).get("id");
                    String nextTitle = (String) next.get(0).get("title");
                    articleBean.setNextId(nextId);
                    articleBean.setNextArticleTitle(nextTitle);
                } else {
                    articleBean.setNextId(-1);
                    articleBean.setNextArticleTitle("已经是最后一篇了！");
                }
            }
            r.setSuccess(GlobalVar.SUCCESS);
            r.setData(articleBean);
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            r.setSuccess(GlobalVar.FAIL);
            r.setMsg("加载文章失败！");
            return r;
        }
    }

    @Override
    public Result updateArticleStatus(String id, Integer status) {
        Result r = new Result();
        if (id == null || status == null) {
            r.setSuccess(GlobalVar.FAIL);
            r.setMsg("参数错误，更新失败！");
            return r;
        }
        try {
            articleDao.updateArticleStatus(EncryptUtil.customDecrypt(id), status);
            r.setSuccess(GlobalVar.SUCCESS);
            r.setMsg("更新状态成功！");
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            r.setSuccess(GlobalVar.FAIL);
            r.setMsg("更新状态失败！");
            return r;
        }
    }

    @Override
    public Result updateArticle(ArticleBean articleBean, String ecnryptId) {
        Result r = new Result();
        try {
            int userId = SessionScope.getLoginAuth().getUser().getId();
            articleBean.setUser_id(userId);
            articleBean.setNotEncryptId(EncryptUtil.customDecrypt(ecnryptId));//解密id
            int count = articleDao.updateArticle(articleBean);
            if (count == 1) {
                r.setSuccess(GlobalVar.SUCCESS);
                r.setMsg("更新成功！");
            } else {
                r.setSuccess(GlobalVar.FAIL);
                r.setMsg("更新失败！");
            }
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            r.setSuccess(GlobalVar.FAIL);
            r.setMsg("更新失败！");
            return r;
        }
    }

    @Override
    public Result getQnyToken(String key_prefix, String bucketName) {
        Result res = new Result();
        Auth auth = Auth.create(GlobalVar.QNY_ACCESS_KEY, GlobalVar.QNY_SECRET_KEY);
        String token = auth.uploadToken(bucketName);
        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        map.put("key_prefix", key_prefix + "/" + Instant.now().toEpochMilli());
        System.out.println(map);
        res.setData(map);
        res.setSuccess(GlobalVar.SUCCESS);
        return res;
    }

    @Override
    public Result delQnyArtFile(String key, String type) throws QiniuException {
        Result res = new Result();
        if (key == null || key.length() <= 0) {
            res.setSuccess(GlobalVar.FAIL);
            res.setMsg("资源空间为空，删除文件失败!");
            return res;
        }
        String bucketName = "";
        if (type != null && type.equals("banner")) {
            bucketName = GlobalVar.QNY_ARTICLE_BUCKET;
        } else if (type != null && type.equals("demoZip")) {
            bucketName = GlobalVar.QNY_DEMO_BUCKET;
        } else {
            res.setSuccess(GlobalVar.FAIL);
            res.setMsg("无法识别的资源类型,删除失败！");
            return res;
        }
        Auth auth = Auth.create(GlobalVar.QNY_ACCESS_KEY, GlobalVar.QNY_SECRET_KEY);
        Zone z = Zone.zone0();
        Configuration c = new Configuration(z);
        BucketManager bucketManager = new BucketManager(auth, c);
        bucketManager.delete(bucketName, key);
        res.setSuccess(GlobalVar.SUCCESS);
        res.setMsg("删除文件成功！");
        return res;
    }

    @Override
    public Result getDownLoadUrl(String artId, HttpServletRequest request) throws UnsupportedEncodingException {
        Result res = new Result();
        if (artId == null) {
            res.setMsg("下载失败，请刷新页面重试！");
            res.setSuccess(GlobalVar.FAIL);
            return res;
        }
        String ip = StringUtil.getIpAddr(request);
        Integer id = EncryptUtil.customDecrypt(artId);
        boolean artIsDownload = DataToCache.getArticleIsDownload(String.valueOf(id), ip);
        if (!artIsDownload) {
            res.setSuccess(GlobalVar.FAIL);
            res.setMsg("为节省资源，24小时内只能下载一次！");
            return res;
        }
        //查看ip是否评论过本文章
        Integer commId = commentDao.getisComm(id, ip);
        if (commId == null) {
            res.setSuccess(GlobalVar.FAIL);
            res.setMsg("评论之后才可以下载哦！^_^");
            return res;
        }
        //获取文章演示zip下载地址
        Map<String, String> map = articleDao.getArticleZipUrlById(id);
        String zipUrl = map.get("zip_url");
        String fileName = map.get("title") + zipUrl.substring(zipUrl.lastIndexOf("."));
        if (zipUrl == null || zipUrl.length() <= 0) {
            res.setMsg("下载失败，请刷新页面重试！");
            res.setSuccess(GlobalVar.FAIL);
            return res;
        }
        String domainOfBucket = GlobalVar.QNY_DEMO_URL + "/" + zipUrl + "?attname=";
        String encodedFileName = URLEncoder.encode(fileName, "utf-8");
        String publicUrl = String.format("%s/%s", domainOfBucket, encodedFileName);
        int index = publicUrl.lastIndexOf("/");
        StringBuilder sb = new StringBuilder(publicUrl);
        sb.replace(index, index + 1, "");
        Auth auth = Auth.create(GlobalVar.QNY_ACCESS_KEY, GlobalVar.QNY_SECRET_KEY);
        String downloadRUL = auth.privateDownloadUrl(sb.toString(), GlobalVar.QNY_EXPIRE_SECONDS);
        System.out.println(downloadRUL);
        //添加ip到缓存
        DataToCache.setDownloadIpToArtId(String.valueOf(id), ip);
        res.setSuccess(GlobalVar.SUCCESS);
        res.setMsg("生成下载连接成功！");
        res.setData(downloadRUL);
        return res;

    }

    @Override
    public Result updateBannerUrl(String artId, String key, String oldKey) {
        Result res = new Result();
        //更新图片路径
        int count = articleDao.updateBannerUrl(EncryptUtil.customDecrypt(artId), key);
        if (count == 1) {
            //删除七牛上的老banner
            Auth auth = Auth.create(GlobalVar.QNY_ACCESS_KEY, GlobalVar.QNY_SECRET_KEY);
            Zone z = Zone.zone0();
            Configuration c = new Configuration(z);
            BucketManager bucketManager = new BucketManager(auth, c);
            try {
                bucketManager.delete(GlobalVar.QNY_ARTICLE_BUCKET, oldKey);
                res.setSuccess(GlobalVar.SUCCESS);
                res.setMsg("更新Banner成功！");
            } catch (QiniuException e) {
                e.printStackTrace();
                res.setSuccess(GlobalVar.FAIL);
                res.setMsg("更新图片路径成功，但是删除七牛云老banner失败！");
            }
        } else {
            res.setMsg("更新图片信息失败！");
            res.setSuccess(GlobalVar.FAIL);
        }
        return res;
    }

    @Override
    public Result updateZipFileUrl(String artId, String key, String oldKey) {
        Result res = new Result();
        //更新演示文件路径
        int count = articleDao.updateZipFileUrl(EncryptUtil.customDecrypt(artId), key);
        if (count == 1) {
            //删除七牛上的老banner
            Auth auth = Auth.create(GlobalVar.QNY_ACCESS_KEY, GlobalVar.QNY_SECRET_KEY);
            Zone z = Zone.zone0();
            Configuration c = new Configuration(z);
            BucketManager bucketManager = new BucketManager(auth, c);
            try {
                bucketManager.delete(GlobalVar.QNY_DEMO_BUCKET, oldKey);
                res.setSuccess(GlobalVar.SUCCESS);
                res.setMsg("更新演示文件成功！");
            } catch (QiniuException e) {
                e.printStackTrace();
                res.setSuccess(GlobalVar.FAIL);
                res.setMsg("更新演示文件路径成功，但是删除七牛云老文件失败！");
            }
        } else {
            res.setMsg("更新演示文件信息失败！");
            res.setSuccess(GlobalVar.FAIL);
        }
        return res;
    }

    @Override
    public void recordArtCount(String artId) {
        if (artId != null) {
            Integer id = EncryptUtil.customDecrypt(artId);
            articleDao.recordArtCount(id);
        }
    }

    @Override
    public PageInfo<ArticleBean> getArticleAll(Map<String, String> param) {
        PageHelper.startPage(Integer.valueOf(param.get("pageNum")), Integer.valueOf(param.get("pageSize")));
        List<ArticleBean> list = articleDao.getArticleAll(param);
        PageInfo<ArticleBean> pageInfo = new PageInfo<>(list);
        List<ArticleBean> collect = pageInfo.getList().stream().map(x -> {
            x.setFront_img(GlobalVar.QNY_ARTICLE_URL + "/" + x.getFront_img());
            x.setContent("");
            return x;
        }).collect(Collectors.toList());
        pageInfo.setList(collect);
        return pageInfo;
    }
}
